package com.damionew.website.conf;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.damionew.website.shiro.MyShiroRealm;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

import java.util.*;

/**
 * Shiro 配置
 *
 Apache Shiro 核心通过 Filter 来实现，就好像SpringMvc 通过DispachServlet 来主控制一样。
 既然是使用 Filter 一般也就能猜到，是通过URL规则来进行过滤和权限校验，所以我们需要定义一系列关于URL的规则和访问权限。
 *
 */
@Configuration
public class ShiroConfiguration {
    /**
     * 拦截器
     * @param securityManager
     * @return shiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager((org.apache.shiro.mgt.SecurityManager) securityManager);
        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/static/**", "anon");
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        //<!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边 -->:这是一个坑呢，一不小心代码就不好使了;
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/**", "authc");
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        // 仍然是通過controller請求响应
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/menu/index");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }	
    	/**
    	 * 凭证匹配器，此处使用md5算法，散列两次 
    	 * 已经将密码校验交给了MyShiroRealam中SimpleAuthenticationInfo
    	 * @return hashedCredentialsMatcher
    	 */
    	@Bean
    	public HashedCredentialsMatcher hashedCredentialsMatcher() {
    	    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    	    hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法 
    	    hashedCredentialsMatcher.setHashIterations(2);//散列次数md5(md5(""))
    	    return hashedCredentialsMatcher;
    	}
    	/**
    	 * 后台管理域
    	 * 账号密码验证；授权
    	 * @return myShiroRealm
    	 */
    	@Bean
    	public MyShiroRealm myShiroRealm(){
    	    MyShiroRealm myShiroRealm = new MyShiroRealm();
   	    myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
    	    return myShiroRealm;
    	}
    	@Bean
    	public ShiroDialect shiroDialect() {
    	    return new ShiroDialect();
    	}
    	/**
    	 * 安全管理器
    	 * 所有配置的入口；所有与安全相关的操作都会与SecurityManager交互，且管理着所有的Subject
    	 * 实现验证，授权，Session管理操作的接口
    	 * @return securityManager
    	 */
	@Bean
	public SecurityManager securityManager(){
		DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
		securityManager.setRealm(myShiroRealm());
		return securityManager;
	}
	/**
	 * 开启shiro aop注解支持，使用代理方式；所以需要开启代码支持？？？？
	 * @param securityManager
	 * @return authorizationAttributeSourceAdvisor
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
	    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
	    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
	    return authorizationAttributeSourceAdvisor;
	}
}